package com.zzl.bonds.ticket.untils;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

/**
 * 票据编号 工具类
 *
 * @author : spp
 * @date : 2022/2/16 20:43
 */
@Component
public class TicketNoUtils {


    private TicketNoUtils() {
    }

    /**
     * 凭证编号
     */
    private static final String TICKET = "EC";

    /**
     * 业务编号
     */
    private static final String BUSINESS = "NYY";
    private static final String SIGN_OPEN = "UVM=";
    /**
     * 转单编号
     */
    private static final String TRANSFER = "WlI=";
    private static final String SIGN_TRANSFER = "UVM=";
    /**
     * 融单编号
     */
    private static final String FINANCE = "UloK";
    private static final String CASHING = "REY=";
    private static final String EXCEPTION = "WUM=";

    private static final String DATE_FORMAT = "yyMMdd";
    private static final String TIME_FORMAT = "HHmmss";

    private static Random random;

    static {
        random = new SecureRandom();
    }

    /**
     * 随机码(2)+年月日时分秒微秒+随机码(2)
     *
     * @return 票据编号
     */
    public static String getTicketNo() {
        int ends1 = random.nextInt(99);
        int ends2 = random.nextInt(99);
        //如果不足两位，前面补0
        String start = String.format("%02d", ends1);
        String end = String.format("%02d", ends2);
        String time = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
        return start + time + end;
    }

    /**
     * EC+yymmdd+6位时分秒（24h制，秒数以第二步点击提交为节点）+4位流水号（16进制）
     * eg：EC220506153623001
     *
     * @param redisTemplate redis
     * @return 开立申请订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, TICKET);
    }

    public static String getBusinessNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, BUSINESS);
    }


    /**
     * 前缀+8位日期+六位序列号（十六进制从0000自增）
     *
     * @param redisTemplate redis
     * @return 开立签收订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketSignOpenNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, SIGN_OPEN);
    }

    /**
     * 前缀+8位日期+六位序列号（十六进制从0000自增）
     *
     * @param redisTemplate redis
     * @return 转让申请订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketTransferNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, TRANSFER);
    }

    /**
     * 前缀+8位日期+六位序列号（十六进制从0000自增）
     *
     * @param redisTemplate redis
     * @return 转让签收订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketSignTransferNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, SIGN_TRANSFER);
    }

    /**
     * 前缀+8位日期+六位序列号（十六进制从0000自增）
     *
     * @param redisTemplate redis
     * @return 融资申请订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketFinanceNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, FINANCE);
    }

    /**
     * 前缀+8位日期+六位序列号（十六进制从0000自增）
     *
     * @param redisTemplate redis
     * @return 兑付申请订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketCashingNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, CASHING);
    }

    /**
     * 前缀+8位日期+六位序列号（十六进制从0000自增）
     *
     * @param redisTemplate redis
     * @return 异常申请订单号
     */
    @SuppressWarnings({"rawtypes"})
    public static String getTicketExceptionNo(RedisTemplate redisTemplate) {
        return createNo(redisTemplate, EXCEPTION);
    }

    /**
     * EC+yymmdd+6位时分秒（24h制，秒数以第二步点击提交为节点）+4位流水号（16进制）
     *
     * @param redisTemplate
     * @param prefix
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private static String createNo(RedisTemplate redisTemplate, String prefix) {
        Date now = new Date();
        //日期
        String key = prefix + DateUtils.dateFormat(now, DATE_FORMAT);
        //时间
        String key2 = DateUtils.dateFormat(now, TIME_FORMAT);
        Long increment = redisTemplate.opsForValue().increment(key, 1);
        if (increment == null) {
            increment = 0L;
        }
        if (1L == increment) {
            Date nextDay = DateUtils.nextSomeDay(now, 1);
            Date nextDayNoHour = DateUtils.string2Date(DateUtils.dateFormat(nextDay, DATE_FORMAT), DATE_FORMAT);
            if (nextDayNoHour != null) {
                redisTemplate.expireAt(key, nextDayNoHour);
            }
        }
        return key + key2 + String.format("%04x", increment.intValue()).toUpperCase();
    }
}
